/*
 * twi_interface.c
 *
 *  Created on: Oct 8, 2011
 *  Author: Mario H. Voorsluys
 *	email: forcaeluz@gmail.com
 *
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Library General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, visit:
 * http://www.gnu.org/copyleft/gpl.html
 */
#include "twi_interface.h"

void twi_init(){
	last_status=0x00;
	PORTC |= (1 << PIN0)|(1<<PIN1);
	TWSR = (1<<TWPS0)|(1<<TWPS1);
	TWBR = (unsigned char)((12000000 / 100)-16)/2;
}

void twi_master_start(){
	int count = 0;
	last_status = 0x00;
	while(count < 3){
		TWCR = (1 << TWSTA)|(1 << TWINT)|(1 << TWEN);
		//Wait for TWINT flag.
		while(!(TWCR & (1 << TWINT)));
		if(TW_STATUS == TW_START || TW_STATUS == TW_REP_START)
			return;
		else
			count++;
	}
	last_status = TW_STATUS;
}


void twi_master_tx_slave(unsigned char addr, int read){
	int count = 0;
	while(count < 3){
		if(read)
			TWDR = addr|TW_READ;
		else
			TWDR = addr|TW_WRITE;

		TWCR = (1 << TWINT)|(1 << TWEN);
		//Wait for TWINT flag.
		while(!(TWCR & (1 << TWINT)));
		if(TW_STATUS == TW_MT_SLA_ACK || TW_STATUS == TW_MR_SLA_ACK)
			return;
		else
			count++;
	}
	last_status = TW_STATUS;
}

void twi_master_tx_data(unsigned char data){
	int count = 0;
	while(count < 3){
		TWDR = data;
		//Wait for TWINT flag.
		TWCR = (1 << TWINT)|(1 << TWEN);
		while(!(TWCR & (1 << TWINT)));
		if(TW_STATUS == TW_MT_DATA_ACK)
			return;
		else
			count++;
	}
	last_status = TW_STATUS;
}


void twi_send_start(unsigned char taddr){
	twi_master_start();
	twi_master_tx_slave(taddr, 0);
}

void twi_finish(){
	TWCR = (1 << TWINT)|(1 << TWEN)|(1 << TWSTO);
}

unsigned char twi_request(unsigned char addr, int pos){
	unsigned char data;
	twi_send_start(addr);
	twi_master_tx_data(pos);
	twi_master_start();
	twi_master_tx_slave(addr, 1);
	data = twi_read_data(0);
	twi_finish();

	return data;
}

unsigned char twi_read_data(int ack){
	int count = 0;
	while(count < 3){
		if(ack){
			TWCR = (1 << TWINT)|(1<<TWEN)|(1<<TWEA);
			while(!(TWCR & (1 << TWINT)));
			if(TW_STATUS == TW_MR_DATA_ACK){
				unsigned char data = TWDR;
				return data;
			}else{
				count++;
			}
		}else{
			TWCR = (1 << TWINT)|(1<<TWEN);
			while(!(TWCR & (1 << TWINT)));
			if(TW_STATUS == TW_MR_DATA_NACK){
				unsigned char data = TWDR;
				return data;
			}else{
				count++;
			}
		}
	}
	last_status = TW_STATUS;
	return 0xFF;
}

unsigned char twi_buffered_value(int pos){
	return buffer[pos];
}

int sonar_distance(){
	return PORTB = buffer[0];
}
